package org.yinxianren.java.test.thread;

import java.util.ArrayDeque;
import java.util.Date;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *     Java有一种特别的线程叫做守护线程。这种线程的优先级非常低，通常在程序里没有其他线程运行时才会执行它。
 * 当守护线程是程序里唯一在运行的线程时，JVM会结束守护线程并终止程序。
 * 根据这些特点守护线程通常用于在同一程序里给普通线程（也叫使用者线程）提供服务。
 *  它们通常无限循环的等待服务请求或执行线程任务。它们不能做重要的任务，因为我们不知道什么时候会被分配到CPU时间片，
 *  并且只要没有其他线程在运行，它们可能随时被终止。JAVA中最典型的这种类型代表就是垃圾回收器。，
 * 在这个指南中, 我们将学习如何创建一个守护线程，开发一个用2个线程的例子；我们的使用线程会写事件到queue,
 * 守护线程会清除queue里10秒前创建的事件。
 */
public class WriterTask implements Runnable {

    private Deque<Event> deque;
    private AtomicInteger count=new AtomicInteger(0);
    public WriterTask (Deque<Event> deque){
        this.deque=deque;
    }

    //实现这个任务的 run() 方法 。 此方法有100个循环。在每个循环中我们会创建 一个Event对象，
    // 并保存到 queue里， 然后休眠1秒。
    public void run() {
        for (int i=1; i<100; i++) {
            int co= count.incrementAndGet();
            System.out.println("i==="+co);
            Event event=new Event();
            event.setDate(new Date());
            event.setEvent(String.format("The thread %s has generated an  event",Thread.currentThread().getId()));
            deque.addFirst(event);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
class CleanerTask extends Thread {
    private Deque<Event> deque;
    public CleanerTask(Deque<Event> deque) {
        this.deque = deque;
        setDaemon(true);//让此线程成为守护线程
    }
    @Override
    public void run() {
            while (true) {
            Date date = new Date();
            clean(date);
        }
    }


    /**
     *  它获取最后的事件，如果它在10秒前被创建，就删除它并查看下一个事件。
     *  如果一个事件被删除，它会写一个事件信息和queue的新的大小，为了让你看到变化过程。
     * @param date
     */
    private void clean(Date date) {
        long difference;
        boolean delete;
        if (deque.size()==0) {
            return;
        }
        delete=false;
        do {
            Event e = deque.getLast();
            difference = date.getTime() - e.getDate().getTime();
            if (difference > 10000) {
                System.out.println("Cleaner:"+e.getEvent());
                deque.removeLast();
                delete=true;
            }
        } while (difference > 10000);

        if (delete){
            System.out.println("Cleaner: Size of the queue: "+deque.size());
        }
    }

}

class Event{

    private Date date;
    private String event;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getEvent() {
        return event;
    }

    public void setEvent(String event) {
        this.event = event;
    }
}

class MainSix{

    public static void main(String[] args) {
        Deque<Event> deque=new ArrayDeque<Event>();
        // 任务线程
        WriterTask writer=new WriterTask(deque);
        for (int i=0; i<3; i++){
            Thread thread=new Thread(writer);
            thread.start();
        }
        //守护线程
        CleanerTask cleaner=new CleanerTask(deque);
        cleaner.start();



    }
}